#include "BondCDCPriceInfo.h"
#include "BondContainer.h"
#include "BondCalendar.h"
#include <core/Utility.h>
#include <core/time/date.h>
#include <uam/ServerTimeMgr.h>
#include <qglobal.h>

CBondCDCPriceInfo::CBondCDCPriceInfo()
{
	m_mpCdcContainer.reserve(1024*64);
}

CBondCDCPriceInfo& CBondCDCPriceInfo::instance()
{
	static CBondCDCPriceInfo cdcpi;
	return cdcpi;
}

void CBondCDCPriceInfo::ClearAll()
{
	SCOPED_LOCK(m_mutex);
	m_mpCdcContainer.clear();
	m_updateDate = 0;
	m_updateDateSpec = 0;
}

void CBondCDCPriceInfo::ClearNonSpecial()
{
	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::iterator it = m_mpCdcContainer.begin();
	for (; it != m_mpCdcContainer.end();)
	{
		if (!it->second.isSpecial())
		{
			it = m_mpCdcContainer.erase(it);
		}
		else it++;
	}
	m_updateDate = 0;
}

void CBondCDCPriceInfo::ClearSpecial()
{
	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::iterator it = m_mpCdcContainer.begin();
	for (; it != m_mpCdcContainer.end();)
	{
		if (it->second.isSpecial())
		{
			it = m_mpCdcContainer.erase(it);
		}
		else it++;
	}
	m_updateDateSpec = 0;
}


void CBondCDCPriceInfo::Add(const int nBondIndex, const xQBACDCPriceUnit_c& unit, bool bSpecial) //需要外部加锁
{
	int nPrcType = GetCdcPrcType(unit);
	CBondCdcPriceUnit& pu = m_mpCdcContainer[nBondIndex];
	pu.Add(nPrcType, unit, bSpecial);

	if (bSpecial)
		m_updateDateSpec = qMax(m_updateDateSpec, unit.m_Date);
	else
		m_updateDate = qMax(m_updateDate, unit.m_Date);
}

uint32_t CBondCDCPriceInfo::GetEstimateDate(const int nBondIndex)
{
	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::iterator it = m_mpCdcContainer.find(nBondIndex);
	if (it == m_mpCdcContainer.end()) 	return 0;
	CBondCdcPriceUnit& bondCdc = it->second;
	return bondCdc.GetEstimateDate();
}

int CBondCDCPriceInfo::GetCdcPrcType(const xQBACDCPriceUnit_c& unit)
{
	int nPriceType = est_type_null;
	if (strcmp(unit.m_est_option, "行权") == 0){
		nPriceType = est_type_exercise;
	}
	else if (strcmp(unit.m_est_option, "到期") == 0){
		nPriceType = est_type_expire;
	}
	return nPriceType;
}

bool CBondCDCPriceInfo::IsPriceValid(const char* pPrc, bool bIsCdc)
{
	if (!pPrc) return false;
	if (pPrc[0] == '\0')return false;
	if(bIsCdc && strcmp(pPrc, "0") == 0)return false;
	if(!bIsCdc && ( strcmp(pPrc, "Bid") == 0 || strcmp(pPrc, "bid") == 0 || strcmp(pPrc, "ofr") == 0 || strcmp(pPrc, "Ofr") == 0))return false;
	return true;
	
}

std::string CBondCDCPriceInfo::GetSplit()
{
    static std::string strSplit = "/";
	return strSplit;
}

std::string	CBondCDCPriceInfo::GetCDCPriceYesterday(int& nOptType, const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType, bool bSingle)
{
	std::string strPrc;
	char sPrc[11] = { 0 };
	nOptType = CBondCDCPriceInfo::est_type_invalid;
	if (!bIsCdcAuthValid) return sPrc;//无估值权限

	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::const_iterator it = m_mpCdcContainer.find(nBondIndex);
	if (it == m_mpCdcContainer.end()) return sPrc; //无估值数据

	const CBondCdcPriceUnit& bondCdc = it->second;
	if (bondCdc.GetSize() == 0) return sPrc; //无估值数据

	uint32_t nDate = bondCdc.GetEstimateDate();
	if (nDate <= 0)return sPrc; //无估值数据

	bool bSpec = bondCdc.isSpecial();
	if (bSpec && nDate != m_updateDateSpec)return sPrc;
	else if (!bSpec && nDate != m_updateDate)return sPrc;// 估值日期不匹配

	bool bYesterday = false;//未获取今日估值
	if (isTodayDataValid(bSpec))bYesterday = true;//今日估值有效时

	for (int i = CBondCDCPriceInfo::est_type_exercise; i <= est_type_null; ++i)
	{
		if (bondCdc.GetEstimateElement(sPrc, _countof(sPrc), i, nPrcType, bYesterday))
		{
			if (sPrc[0] != '\0')
			{
				if (!strPrc.empty()) strPrc += GetSplit();
				strPrc += sPrc;
			}

			if (nOptType == CBondCDCPriceInfo::est_type_exercise && i == CBondCDCPriceInfo::est_type_expire)
				nOptType = CBondCDCPriceInfo::est_type_combine;
			else
				nOptType = i;

			if (bSingle)break;
		}
	}
	return strPrc;
}

std::string	CBondCDCPriceInfo::GetCDCPriceToday(int& nOptType, const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType, bool bSingle)
{
	std::string strPrc;
	char sPrc[11] = { 0 };
	nOptType = CBondCDCPriceInfo::est_type_invalid;
	if (!bIsCdcAuthValid) return sPrc;//无估值权限

	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::const_iterator it = m_mpCdcContainer.find(nBondIndex);
	if (it == m_mpCdcContainer.end()) return sPrc; //无估值数据

	const CBondCdcPriceUnit& bondCdc = it->second;
	if (bondCdc.GetSize() == 0) return sPrc; //无估值数据

	uint32_t nDate = bondCdc.GetEstimateDate();
	if (nDate <= 0)return sPrc; //无估值数据

	bool bSpec = bondCdc.isSpecial();
	if (bSpec && nDate != m_updateDateSpec)return sPrc;
	else if (!bSpec && nDate != m_updateDate)return sPrc;// 估值日期不匹配

	if (!isTodayDataValid(bSpec))return sPrc;//无今日数据

	for (int i = CBondCDCPriceInfo::est_type_exercise; i <= est_type_null; ++i)
	{
		if (bondCdc.GetEstimateElement(sPrc, _countof(sPrc), i, nPrcType, false))
		{
			if (sPrc[0] != '\0')
			{
				if (!strPrc.empty()) strPrc += GetSplit();
				strPrc += sPrc;
			}

			if (nOptType == CBondCDCPriceInfo::est_type_exercise && i == CBondCDCPriceInfo::est_type_expire)
				nOptType = CBondCDCPriceInfo::est_type_combine;
			else
				nOptType = i;

			if (bSingle)break;
		}
	}
	return strPrc;
}

std::string CBondCDCPriceInfo::GetCDCPriceLast(int& nOptType, const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType, bool bSingle)
{
	std::string strPrc;
	char sPrc[11] = { 0 };
	nOptType = CBondCDCPriceInfo::est_type_invalid;
	if (!bIsCdcAuthValid) return sPrc;//无估值权限

	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::const_iterator it = m_mpCdcContainer.find(nBondIndex);
	if (it == m_mpCdcContainer.end()) return sPrc; //无估值数据

	const CBondCdcPriceUnit& bondCdc = it->second;
	if (bondCdc.GetSize() == 0) return sPrc; //无估值数据

	uint32_t nDate = bondCdc.GetEstimateDate();
	if (nDate <= 0)return sPrc; //无估值数据

	bool bSpec = bondCdc.isSpecial();
	if (bSpec && nDate != m_updateDateSpec)return sPrc;
	else if (!bSpec && nDate != m_updateDate)return sPrc;// 估值日期不匹配

	for (int i = CBondCDCPriceInfo::est_type_exercise; i <= est_type_null; ++i)
	{
		if (bondCdc.GetEstimateElement(sPrc, _countof(sPrc), i, nPrcType, false))
		{
			if (sPrc[0] != '\0')
			{
				if (!strPrc.empty()) strPrc += GetSplit();
				strPrc += sPrc;
			}

			if (nOptType == CBondCDCPriceInfo::est_type_exercise && i == CBondCDCPriceInfo::est_type_expire)
				nOptType = CBondCDCPriceInfo::est_type_combine;
			else
				nOptType = i;

			if (bSingle)break;
		}
	}
	return strPrc;
}

std::string CBondCDCPriceInfo::GetCDCPriceYesterdayByOpt(int& nOptType, const bool bIsCdcAuthValid, const int nBondIndex, const int nOptTypeStart, const int nPrcType)
{
	char sPrc[11] = { 0 };
	nOptType = CBondCDCPriceInfo::est_type_invalid;
	if (!bIsCdcAuthValid) return sPrc;

	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::const_iterator it = m_mpCdcContainer.find(nBondIndex);
	if (it == m_mpCdcContainer.end()) return sPrc;

	const CBondCdcPriceUnit& bondCdc = it->second;
	if (bondCdc.GetSize() == 0) return sPrc;

	uint32_t nDate = bondCdc.GetEstimateDate();
	if (nDate <= 0)return sPrc; //无估值数据

	bool bSpec = bondCdc.isSpecial();
	if (bSpec && nDate != m_updateDateSpec)return sPrc;
	else if (!bSpec && nDate != m_updateDate)return sPrc;// 估值日期不匹配

	bool bYesterday = false;//未获取今日估值
	if (isTodayDataValid(bSpec))bYesterday = true;//今日估值有效时

	for (int i = nOptTypeStart; i <= est_type_null; ++i) {
		if (bondCdc.GetEstimateElement(sPrc, _countof(sPrc), i, nPrcType, bYesterday)) {
			if (sPrc[0] != '\0') {
				nOptType = i;
				break;
			}
		}
	}

	return sPrc;
}

std::string CBondCDCPriceInfo::GetRelaEstimatePrice(const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType /*= 0/*price_type_yield*/, const char* pRef /*= nullptr*/, bool bYesterday /*= false*/)
{
	char sPrc[11] = { 0 };
	char sTmp[11] = { 0 };
	if (!bIsCdcAuthValid) return sPrc;
	bool bRefValid = IsPriceValid(pRef);
	{
		SCOPED_LOCK(m_mutex);
		std::unordered_map<int, CBondCdcPriceUnit>::iterator it = m_mpCdcContainer.find(nBondIndex);
		if (it == m_mpCdcContainer.end()) 	return sPrc;
		const CBondCdcPriceUnit& bondCdc = it->second;
		if (bondCdc.GetSize() == 0) return sPrc;
		double dGap = INVALID_CDC_VALUE;
		for (int i = CBondCDCPriceInfo::est_type_exercise; i <= est_type_null; ++i){
			if(! bondCdc.GetEstimateElement(sTmp, _countof(sTmp), i, nPrcType, bYesterday))continue;
			if (!bRefValid && IsPriceValid(sTmp, true)){
				FIELDCOPY(sPrc, sTmp);
				break;
			}
			bool bCalcuValid = IsPriceValid(sTmp, true) ? bRefValid : false;
			if (!bCalcuValid){ //保存的中债估值存在无效值
				continue;
			}
			double dTmp = atof(pRef) -  atof(sTmp);
			if (abs(dTmp) > abs(dGap)) continue;
			dGap = dTmp;
			FIELDCOPY(sPrc, sTmp);
		}
	}
	return sPrc;
}

void CBondCDCPriceInfo::GetExerciseAndMaturity(const bool bIsCdcAuthValid, const int nBondIndex, double &dExercise, double &dMaturity)
{
	dExercise = INVALID_CDC_VALUE;
	dMaturity = INVALID_CDC_VALUE;

	if (!bIsCdcAuthValid)
		return;

	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::iterator itrFind = m_mpCdcContainer.find(nBondIndex);
	if (itrFind == m_mpCdcContainer.end())
		return;

	char sPrc[11] = { 0 };

	CBondCdcPriceUnit& CdcUnit = itrFind->second;
	for (int i = CBondCDCPriceInfo::est_type_exercise; i <= est_type_null; ++i)
	{
        memset(sPrc, 0, sizeof(sPrc));

		if (i == est_type_exercise)
		{
			if (CdcUnit.GetEstimateElement(sPrc, sizeof(sPrc), i, price_type_yield, false) && IsPriceValid(sPrc,true))
			{
				dExercise = atof(sPrc);
			}
		}
		else if (i == est_type_expire)
		{
			if (CdcUnit.GetEstimateElement(sPrc, sizeof(sPrc), i, price_type_yield, false) && IsPriceValid(sPrc, true))
			{
				dMaturity = atof(sPrc);
			}
		}
	}

	if (dExercise <= INVALID_CDC_VALUE && dMaturity <= INVALID_CDC_VALUE )
	{
		if (CdcUnit.GetEstimateElement(sPrc, sizeof(sPrc), est_type_null, price_type_yield, false) && IsPriceValid(sPrc, true))
			dMaturity = atof(sPrc);
	}
}

bool CBondCDCPriceInfo::isTodayDataValid(bool bSpec)
{
	static uint32_t dateLastCalc = 0;
	static bool isHoliday = false;
	uint32_t today = qb::base::IntDate::timeToInt(ServerTimeMgr::instance().serverTime());
	if (today != dateLastCalc)
	{
		int nToday = (int)today;
		isHoliday = CBondCalendar::instance().IsHoliday("CNY", "CIB", nToday);
		dateLastCalc = today;
	}

	if (bSpec)
	{
		if (m_updateDateSpec == qb::base::IntDate::timeToInt(ServerTimeMgr::instance().serverTime()))
		{//今日估值已收到
			return true;
		}
		else
		{//今日估值未收到
			if (isHoliday)
				return true;
			else
				return false;
		}
	}
	else
	{
		if (m_updateDate == qb::base::IntDate::timeToInt(ServerTimeMgr::instance().serverTime()))
		{//今日估值已收到
			return true;
		}
		else
		{//今日估值未收到
			if (isHoliday)
				return true;
			else
				return false;
		}
	}

	return false;
}

double CBondCDCPriceInfo::GetYesterdayCDCPriceGap(const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType /*=price_type_yield*/, bool bReverse, const char* pRef /*= nullptr*/, const double dRef /*= INVALID_CDC_VALUE*/, bool bForceExercise /*=false*/)
{
	char sPrc[11] = { 0 };
	if (!bIsCdcAuthValid) return INVALID_CDC_VALUE;
	if (!CBondContainer::instance().IsValidIndex(nBondIndex))return INVALID_CDC_VALUE;
	bool bRefValid = false;
	double dPrc = INVALID_CDC_VALUE;
	if (pRef == nullptr) {
		dPrc = dRef;
		bRefValid = true;
	}
	else {
		bRefValid = IsPriceValid(pRef);
		dPrc = atof(pRef);
	}
	bRefValid = (dPrc > INVALID_CDC_VALUE) ? bRefValid : false;
	double dGap = INVALID_CDC_VALUE;
	if (!bRefValid) return dGap;

	SCOPED_LOCK(m_mutex);
	std::unordered_map<int, CBondCdcPriceUnit>::iterator it = m_mpCdcContainer.find(nBondIndex);
	if (it == m_mpCdcContainer.end()) return dGap;

	const CBondCdcPriceUnit& bondCdc = it->second;
	if (bondCdc.GetSize() == 0) return dGap; //无估值数据

	uint32_t nDate = bondCdc.GetEstimateDate();
	if (nDate <= 0)return dGap; //无估值数据

	bool bSpec = bondCdc.isSpecial();
	if (bSpec && nDate != m_updateDateSpec)return dGap;
	else if (!bSpec && nDate != m_updateDate)return dGap;// 估值日期不匹配

	bool bYesterday = false;//未获取今日估值
	if (isTodayDataValid(bSpec))bYesterday = true;//今日估值有效时

	for (int i = CBondCDCPriceInfo::est_type_exercise; i <= est_type_null; ++i) {
		if (bForceExercise && i == CBondCDCPriceInfo::est_type_expire)continue;
		if (!bondCdc.GetEstimateElement(sPrc, _countof(sPrc), i, nPrcType, bYesterday))continue;
		bool bCalcuValid = IsPriceValid(sPrc, true) ? bRefValid : false;
		if (!bCalcuValid) { //保存的中债估值存在无效值
			continue;
		}
		double dTmp = (bReverse ? dPrc - atof(sPrc) : atof(sPrc) - dPrc) * 100;
		if (fabs(dTmp) > fabs(dGap)) continue;
		dGap = dTmp;
	}

	return dGap;
}

double CBondCDCPriceInfo::GetEstimatePriceGap(const bool bIsCdcAuthValid, const int nBondIndex, const int nPrcType /*= 0/*price_type_yield*/, bool bReverse, const char*  pRef /*= nullptr*/, const double dRef /*= INVALID_CDC_VALUE*/, bool bYesterday /*= false*/, bool bForceExercise /*=false*/)
{
	char sPrc[11] = { 0 };
	if (!bIsCdcAuthValid) return INVALID_CDC_VALUE;
	if (!CBondContainer::instance().IsValidIndex(nBondIndex))return INVALID_CDC_VALUE;
	bool bRefValid = false;
	double dPrc = INVALID_CDC_VALUE;
	if (pRef == nullptr) {
		dPrc = dRef;
		bRefValid = true;
	}
	else{
		bRefValid = IsPriceValid(pRef);
		dPrc = atof(pRef);
	}
	bRefValid = (dPrc > INVALID_CDC_VALUE) ? bRefValid : false;
	double dGap = INVALID_CDC_VALUE;
	if (!bRefValid) return dGap;
	{
		SCOPED_LOCK(m_mutex);
		std::unordered_map<int, CBondCdcPriceUnit>::iterator it = m_mpCdcContainer.find(nBondIndex);
		if (it == m_mpCdcContainer.end()) 	return dGap;
		CBondCdcPriceUnit& bondCdc = it->second;
		for (int i = CBondCDCPriceInfo::est_type_exercise; i <= est_type_null; ++i){
			if (bForceExercise && i == CBondCDCPriceInfo::est_type_expire)continue;
			if (!bondCdc.GetEstimateElement(sPrc, _countof(sPrc), i, nPrcType, bYesterday))continue;
			bool bCalcuValid = IsPriceValid(sPrc, true) ? bRefValid : false;
			if (!bCalcuValid){ //保存的中债估值存在无效值
				continue;
			}
			double dTmp = (bReverse ? dPrc - atof(sPrc) : atof(sPrc) - dPrc) * 100;
			if (fabs(dTmp) > fabs(dGap)) continue;
			dGap = dTmp;
		}
	}
	return dGap;
}

CBondCdcPriceUnit::CBondCdcPriceUnit() : m_bSpecial(false)
{
}

void CBondCdcPriceUnit::Add(const int nPrcType, const xQBACDCPriceUnit_c& unit, bool bSpecial)
{
	static sCDCPrice uEmpty;
	auto it = m_mpBondCdc.find(nPrcType);
	if (it == m_mpBondCdc.end())
	{
		m_mpBondCdc.insert(nPrcType, uEmpty);
		it = m_mpBondCdc.find(nPrcType);
	}
	if (it == m_mpBondCdc.end())return;
	if (it->second.m_nEstDate > unit.m_Date)return;
	else if (it->second.m_nEstDate == unit.m_Date)
	{//同时有效，则使用标准表数据
		if (bSpecial && !m_bSpecial)return;
		if (!bSpecial && m_bSpecial)
		{//如果缓存数据为special表数据，需清空数据，因为special表没有含权数据
			m_mpBondCdc.clear();
			m_mpBondCdc.insert(nPrcType, uEmpty);
			it = m_mpBondCdc.find(nPrcType);
			if (it == m_mpBondCdc.end())return;
		}
	}
	else// cdcUnit.m_nEstDate < unit.m_Date
	{
		if (bSpecial != m_bSpecial)
		{//如果缓存数据为前一天数据，并且来源不是同一张表，需清空数据，因为special表没有含权信息
			m_mpBondCdc.clear();
			m_mpBondCdc.insert(nPrcType, uEmpty);
			it = m_mpBondCdc.find(nPrcType);
			if (it == m_mpBondCdc.end())return;
		}
	}
	sCDCPrice& cdcUnit = it->second;
	FIELDCOPY(cdcUnit.m_sEstcleanprice, unit.m_CleanPrice);
	FIELDCOPY(cdcUnit.m_sEstPrice, unit.m_Yield);
	FIELDCOPY(cdcUnit.m_sFrontEstcleanprice, unit.m_FrontCleanPrice);
	FIELDCOPY(cdcUnit.m_sFrontEstPrice, unit.m_FrontYield);
	FIELDCOPY(cdcUnit.m_sDuration, unit.m_Duration);
	cdcUnit.m_nEstDate = unit.m_Date;
	m_bSpecial = bSpecial;
	return;


// 	sCDCPrice &cdcUnit = m_mpBondCdc[nPrcType];
// 	if (cdcUnit.m_nEstDate > unit.m_Date)return;
// 	else if (cdcUnit.m_nEstDate == unit.m_Date)
// 	{//同时有效，则使用标准表数据
// 		if (bSpecial && !m_bSpecial)return;
// 		if (!bSpecial && m_bSpecial)
// 		{//如果缓存数据为special表数据，需清空数据，因为special表没有含权数据
// 			m_mpBondCdc.clear();
// 			sCDCPrice &cdcUnit2 = m_mpBondCdc[nPrcType];
// 			FIELDCOPY(cdcUnit2.m_sEstcleanprice, unit.m_CleanPrice);
// 			FIELDCOPY(cdcUnit2.m_sEstPrice, unit.m_Yield);
// 			FIELDCOPY(cdcUnit2.m_sFrontEstcleanprice, unit.m_FrontCleanPrice);
// 			FIELDCOPY(cdcUnit2.m_sFrontEstPrice, unit.m_FrontYield);
// 			FIELDCOPY(cdcUnit2.m_sDuration, unit.m_Duration);
// 			cdcUnit2.m_nEstDate = unit.m_Date;
// 			m_bSpecial = bSpecial;
// 			return;
// 		}
// 	}
// 	else// cdcUnit.m_nEstDate < unit.m_Date
// 	{
// 		if (bSpecial != m_bSpecial)
// 		{//如果缓存数据为前一天数据，并且来源不是同一张表，需清空数据，因为special表没有含权信息
// 			m_mpBondCdc.clear();
// 			sCDCPrice &cdcUnit2 = m_mpBondCdc[nPrcType];
// 			FIELDCOPY(cdcUnit2.m_sEstcleanprice, unit.m_CleanPrice);
// 			FIELDCOPY(cdcUnit2.m_sEstPrice, unit.m_Yield);
// 			FIELDCOPY(cdcUnit2.m_sFrontEstcleanprice, unit.m_FrontCleanPrice);
// 			FIELDCOPY(cdcUnit2.m_sFrontEstPrice, unit.m_FrontYield);
// 			FIELDCOPY(cdcUnit2.m_sDuration, unit.m_Duration);
// 			cdcUnit2.m_nEstDate = unit.m_Date;
// 			m_bSpecial = bSpecial;
// 			return;
// 		}
// 	}
// 	FIELDCOPY(cdcUnit.m_sEstcleanprice, unit.m_CleanPrice);
// 	FIELDCOPY(cdcUnit.m_sEstPrice, unit.m_Yield);
// 	FIELDCOPY(cdcUnit.m_sFrontEstcleanprice, unit.m_FrontCleanPrice);
// 	FIELDCOPY(cdcUnit.m_sFrontEstPrice, unit.m_FrontYield);
// 	FIELDCOPY(cdcUnit.m_sDuration, unit.m_Duration);
// 	cdcUnit.m_nEstDate = unit.m_Date;
// 	m_bSpecial = bSpecial;
// 	return;
}

bool CBondCdcPriceUnit::GetEstimateElement(char* const estPrice, const int capacity,const int nOptType, const int nPrcType /*= 0*/, bool bYesterday /*= false*/)const
{
	auto it = m_mpBondCdc.find(nOptType);
	if (it == m_mpBondCdc.end()) return false;
	const char* src = it->second.m_sEstPrice;
	switch (nPrcType)
	{
	case CBondCDCPriceInfo::price_type_yield:
	{
		if (bYesterday)src = it->second.m_sFrontEstPrice;
		break;
	}
	case CBondCDCPriceInfo::price_type_clean:
	{
		if (!bYesterday)src = it->second.m_sEstcleanprice;
		else src = it->second.m_sFrontEstcleanprice;
		if (strcmp(src, "0.0000") == 0)src = NULL;
		break;
	}
	case CBondCDCPriceInfo::price_type_duration:
	{
		src = it->second.m_sDuration;
		break;
	}
	default:
		break;
	}
#if WIN32
    if (src)strncpy_s(estPrice, capacity, src, _TRUNCATE);
#else
    if (src){strncpy(estPrice, src, capacity);
        estPrice[capacity-1] = '\0';}
#endif

	if (!src || *src == '\0') return false;
	return true;
}

uint32_t CBondCdcPriceUnit::GetEstimateDate() const
{
	for (int i = CBondCDCPriceInfo::est_type_exercise; i <= CBondCDCPriceInfo::est_type_null; ++i){
		auto it = m_mpBondCdc.find(i);
		if (it == m_mpBondCdc.end()) continue;
		return it->second.m_nEstDate;
	}

	return 0;
}

int	CBondCdcPriceUnit::GetSize()const
{
	return m_mpBondCdc.size();
}

bool CBondCdcPriceUnit::isSpecial()const
{
	return m_bSpecial;
}

CBondCdcPriceUnit::CDCPriceVec::const_iterator 
CBondCdcPriceUnit::CDCPriceVec::find(int optionType) const
{
	for (auto it = m_values.cbegin(); it != m_values.cend(); ++it)
	{
		if (it->first == optionType)return it;
	}
	return m_values.cend();
}
CBondCdcPriceUnit::CDCPriceVec::iterator
CBondCdcPriceUnit::CDCPriceVec::find(int optionType)
{
	for (auto it = m_values.begin(); it != m_values.end(); ++it)
	{
		if (it->first == optionType)return it;
	}
	return m_values.end();
}
void CBondCdcPriceUnit::CDCPriceVec::insert(int optionType, const sCDCPrice& price)
{
	for (auto it = m_values.begin(); it != m_values.end(); ++it)
	{
		if (it->first == optionType)
		{
			memcpy(&(it->second), &price, sizeof(price));
			return;
		}
	}
	//为防止m_values扩张浪费多余的空间,节省内存,禁用vector内嵌的1/2扩容机制
	if (m_values.size() >= m_values.capacity())
		m_values.reserve(m_values.capacity() + 1);
	m_values.emplace_back(KeyValue{ optionType, price });
}
sCDCPrice& CBondCdcPriceUnit::CDCPriceVec::operator[](int optionType)
{
	for (auto it = m_values.begin(); it != m_values.end(); ++it)
	{
		if (it->first == optionType){
			return it->second;
		}
	}
	//为防止m_values扩张浪费多余的空间,节省内存,禁用vector内嵌的1/2扩容机制
	if (m_values.size() >= m_values.capacity())
		m_values.reserve(m_values.capacity() + 1);
	m_values.emplace_back(KeyValue{ optionType, sCDCPrice{} });
	return m_values[m_values.size() - 1].second;
}
